/*******************************************************************************
  * 文件：printk.c
  * 作者：zyz
  * 版本：v1.0.0
  * 日期：2017-08-03
  * 说明：打印
*******************************************************************************/

/* 头文件 *********************************************************************/
#include "printk.h"
#include "Typedefine.h"
#include "Constant.h"
#include "OS_Buffer.h"
#include "Hardware.h"
#include "Hardware_Uart.h"
#include <stdarg.h>

/* 宏定义 *********************************************************************/
/* 类型定义 *******************************************************************/
/* 变量定义 *******************************************************************/
#if CONFIG_DEBUG
static U8 au8FormatStr[u16PRINTK_BUFFER_SIZE];      // 格式化字符串
static U8 au8PrintData[u16PRINTK_BUFFER_SIZE];      // 打印数据
static Buffer_ts sPrintBuffer;                      // 打印缓冲区
static Bool bPrinting = FALSE;                      // 打印标志
#endif

/* 函数声明 *******************************************************************/
/* 函数定义 *******************************************************************/

/*******************************************************************************
  * 函数名：printk_init
  * 功  能：初始化
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void printk_init(void)
{
#if CONFIG_DEBUG
    // 初始化打印缓冲区
    OS_BufferInit(&sPrintBuffer, au8PrintData, sizeof(au8PrintData));
#endif
}

/*******************************************************************************
  * 函数名：printk
  * 功  能：打印
  * 参  数：const char *format - 格式化字符串
  *         ...                - 可变参数
  * 返回值：打印字符串长度
  * 说  明：无
*******************************************************************************/
int printk(const char *format, ...)
{
#if CONFIG_DEBUG
    va_list arg;
    int len;

    // 格式化字符串
    va_start(arg, format);
    len = vsprintf((char *)au8FormatStr, format, arg);
    va_end(arg);

    // 添加到缓冲区
    if(len > 0)
    {
        // 写入缓冲区
        Hardware_EnterCritical();
        OS_BufferWrite(&sPrintBuffer, au8FormatStr, (U16)len);
        Hardware_ExitCritical();

        // 打印检查
        if(!bPrinting)
        {
            // 设置打印标志
            // 打印处理
            bPrinting = TRUE;
            printk_handler();
        }
    }

    // 返回长度
    return len;
#else
     return 0;
#endif
}

/*******************************************************************************
  * 函数名：printk_handler
  * 功  能：打印处理
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void printk_handler(void)
{
#if CONFIG_DEBUG
    U8 u8Char;
    U16 u16CharNum;

    // 从缓冲区读取字符
    u16CharNum = OS_BufferRemove(&sPrintBuffer, &u8Char, 1);
    // 缓冲区有数据
    if(u16CharNum > 0)
    {
        // 发送字符
        Hardware_Uart2SendByte(u8Char);
    }
    // 缓冲区空了
    else
    {
        // 清除打印标志
        bPrinting = FALSE;
    }
#endif
}

/***************************** 文件结束 ***************************************/
